/*
 * @Description: webSocket自定义封装
 * @Date: 2024-10-23 16:04:02
 * @FilePath: \demod:\12electron\electron-vite-template\src\renderer\src\utils\socket.ts
 */
/*
 * 这里的封装export了三个方法
 * initWebSocket 用来初始化websock，可传入url
 * sendWebsocket 用来发送数据
 * closeWebsocket 用来关闭连接
 */

import { ElMessage } from 'element-plus';
// import { Session } from '/@/utils/storage'; // 引入自定义存储方法

interface IWebSocket {
  url: string; // webSocket地址
  heartbeatTimeCycle?: number; // 心跳周期时间
}

let ws: any = null; // webSocket实例
let socketUrl = 'wss://javascript.info/article/websocket/demo/hello';

let lockReconnect = false; // 是否真正建立连接
let heartbeatTimeCycle: number = 20 * 1000; // 定义心跳周期默认为20s
let timeoutObj: any = null; //心跳心跳倒计时
let serverTimeoutObj: any = null; //心跳倒计时
let timeoutNum: any = null;
let global_callback: any = null;

/**
 * @description: 初始化webSocket
 * @param {string} url 传入的ws链接，例如"wss://javascript.info/article/websocket/demo/hello"
 */
export const initWebSocket = (params: IWebSocket) => {
  socketUrl = params.url; // socket地址
  heartbeatTimeCycle = params.heartbeatTimeCycle || 100000; // 心跳周期

  if (!window.WebSocket) {
    ElMessage.error({
      message: '您的浏览器不支持websocket,请升级或更换浏览器！',
      type: 'error',
      center: true,
    });
    return;
  }
  if (!ws || ws.readyState == 3) {
    ws = new WebSocket(socketUrl); // 实例化WebSocket对象为ws
    socketOnOpen(); // 开启链接
    socketOnClose(); // 监听webSocket是否关闭
    socketOnError(); // 监听webSocket是否出现错误，如果出现则重连
    socketOnMessage(); // 监听后端消息
  }
};

const socketOnOpen = () => {
  ws.onopen = () => {
    console.log('socket连接成功');
    // 开启心跳
    startHeartbeat();
  };
};

const socketOnClose = () => {
  ws.onclose = () => {
    console.log('socket已经关闭');
  };
};

/**
 * @description: 向后端发送webSocket数据
 * @param {any} data 字符串或二进制格式
 */
const socketOnSend = (data: any) => {
  // 如果连接正常
  if (ws.readyState == 1) {
    ws.send(data);
  }
};

const socketOnError = () => {
  ws.onerror = () => {
    reconnect();
    console.log('socket链接错误');
  };
};

// 监听后端返回的信息
const socketOnMessage = () => {
  ws.onmessage = (event: any) => {
    if (event.data.includes('heartbeat')) {
      // 在心跳周期内收到后端消息, 则重置心跳
      resetHeartbeat();
    } else {
      // 把后端返回值给回调函数
      console.log('来自后端的数据---', event.data);
      global_callback(event.data);
    }
  };
};

// 开启心跳
const startHeartbeat = () => {
  timeoutObj && clearTimeout(timeoutObj);
  serverTimeoutObj && clearTimeout(serverTimeoutObj);
  console.log('开启心跳---heartbeatTimeCycle心跳周期：(毫秒)', heartbeatTimeCycle);

  timeoutObj = setTimeout(() => {
    // 如果连接正常
    if (ws.readyState == 1) {
      // 这里发送一个心跳，后端收到后，返回一个心跳消息，
      ws.send('{"heartbeat":"发送给后端的心跳heartbeat"}');
    } else {
      // 否则重连
      reconnect();
    }
    serverTimeoutObj = setTimeout(() => {
      // 超时关闭
      console.log('心跳超时未响应---', heartbeatTimeCycle);
      ws.close();
    }, heartbeatTimeCycle);
  }, heartbeatTimeCycle);
};

//重置心跳
const resetHeartbeat = () => {
  //清除时间
  clearTimeout(timeoutObj);
  clearTimeout(serverTimeoutObj);
  //重启心跳
  startHeartbeat();
};

// 断线重连
const reconnect = () => {
  if (lockReconnect) {
    return;
  }
  lockReconnect = true;
  //没连接上会一直重连，设置延迟避免请求过多
  timeoutNum && clearTimeout(timeoutNum);
  timeoutNum = setTimeout(() => {
    //新连接
    initWebSocket({
      url: socketUrl,
      heartbeatTimeCycle: 20,
    });
    lockReconnect = false;
  }, 5000);
};

export const sendWebsocket = (agentData: any, callback: any) => {
  global_callback = callback;
  socketOnSend(agentData);
};

/**
 * @description: 前端主动关闭链接
 */
export const closeWebsocket = () => {
  if (ws) {
    ws.close();
  }
  clearTimeout(timeoutObj);
  clearTimeout(serverTimeoutObj);
};
